在 Linux 和其他 Unix-like 操作系统中,exec 系列函数和 fork 函数是进程管理中的两个重要组成部分。它们在创建和执行进程时扮演着关键角色,理解它们的工作原理及相互关系对于系统编程至关重要。
一、fork() 函数fork() 是用于创建新进程的系统调用。调用 fork() 后,当前进程(父进程)会被复制一份,生成一个新的进程(子进程)。以下是 fork() 的一些重要特性:
进程复制:子进程是父进程的一个副本,拥有相同的内存空间、打开的文件描述符等。
返回值:fork() 在父进程中返回新创建的子进程的 PID(进程 ID),而在子进程中返回 0。在出错时返回 -1。
并行执行:父进程和子进程会并行执行,操作系统调度它们的执行。
示例代码:123456789101112131415161718#include <stdio.h>#include <unistd.h>int main() { pid_t pid = fork(); if (pid < 0) { perro...
C++的智能指针是RAII的一种应用 自动管理动态内存的工具 可以避免显示的内存释放 减少内存泄漏和为定义行为的可能性 C++标准库提供了三种主要的智能指针 unique_ptr shared_ptr weak_ptr
可能有的同学听过auto_ptr 这个东西在C++11被弃用 在C++17被移除 主要是由于复制问题 可能会导致内存重复释放
unique_ptr这个智能指针对所指对象是独占所有权的 也就是说 同一时刻 只有一个unique_ptr指向这个对象
他不允许复制 但是可以使用move变为右值 再移动赋值 将这个对象的所有权转移到另一个unique_ptr
这个智能指针只需要管理一个对象 开销也比较小 适用于高性能的场景 比如说文件具柄 数据库连接等
12345678910111213141516171819#include <memory>std::unique_ptr<int> createUniquePtr() { return std::make_unique<int>(10);}int main(...
之前有介绍过STL标准模板库 但是那时候由于个人的水平还不足与完全理解 于是再写一篇 让我们重新认识一下STL标准模板库
这里需要数据结构和了解进程地址空间的基础知识
STL库可以说是C++最核心的库之一了 提供了丰富的模板类 函数 让我们能够方便的处理常见的数据结构和算法
STL主要由以下的几个部分组成
容器 Containers
迭代器 iterators
算法 algorithm
函数对象 functors
适配器 adapters
空间配置器 allocators
接下来我们一一对其介绍 尽可能详细的讲解其中的原理
容器容器可以说是STL中最常用的部分之一了 例如vector list map都属于这个内容 主要是为了存储和管理数据
基础的容器主要分为三类 序列式容器 关联式容器 无序容器
还有一种是容器适配器 关于适配器我们后面介绍 这里我们只需要知道他是对上述的三种基础容器进行封装 然后提供特定的功能
每一类下面有很多具体的容器 我们一一来介绍 对于容器中的迭代器和原理我们在迭代器部分介绍
序列式容器序列式容器的特点就是所有的元素都是按顺序存储的 适合用于按顺序处...
什么是多态
多态指的是不同类的对象调用同一个方法时做出不同响应的能力
主要是分为两类
一类是编译时多态 也称静态多态 通过函数重载和运算符重载实现
一类是运行时多态 也称动态多态 通过函数重写(覆盖)实现 具体调用时才决定是哪个函数 使用虚函数实现
什么是重载 重写 重定义
重载指的是在同一个作用域中 函数名相同 但参数列表不同 包括类型\个数\顺序 的函数 返回值不同不算重载 属于静态多态 底层原理是在编译时形成不同的函数名 链接时区分链接
重写指的是在继承关系中子类重新定义继承来的虚函数 重写的函数名\参数列表\返回值类型必须和父类一致 被继承的函数必须是虚函数 可以指定父类显示调用基类的被重写函数 属于动态多态 通过重写子类中的虚函数表实现
重定义指的是在继承关系中 子类重新定义继承来的非虚函数 父类的函数被隐藏 可以使用域作用限定符来访问父类中的同名函数
inline函数可以是虚函数吗
可以 但是inline本身是一个建议的关键字 编译器会忽略inline属性 将其作为虚函数放到虚表中
静态成员函数可以是虚函数吗
不可以 静态成员函数没有t...
在C++中,重载、重写和重定义是经常被提到的三种不同的概念,它们都涉及函数的行为和定义,但在语义、作用范围以及使用场景上有明显的区别。理解这三者的差异有助于更好地掌握C++语言的多态性和函数操作。
重载(Overloading)重载指的是在同一个作用域(同一个类或函数体内),函数名相同但参数列表不同的多个函数共存的现象。重载主要发生在编译时,编译器根据参数的类型、个数来区分调用哪个版本的函数。
特点:
函数名相同,参数类型或数量不同。
发生在同一作用域内。
可以是普通函数的重载,也可以是运算符的重载。
示例:
12345678910class Calculator {public: int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; }};
在这个例子中,add 函数被重载了两次,一个处理整数加法,另一个处理浮点数加法。根据传入的参数类型,编...
在面向对象编程(OOP)中,继承和组合是两种主要的代码复用方式。它们各有优势和适用场景,合理使用可以提高代码的可维护性、可扩展性和灵活性。本文将详细探讨继承和组合的概念、优缺点,并提供指导以帮助开发者选择合适的方式。
继承定义继承是一种用于创建新类的机制,允许新类(子类)从已有类(基类)继承属性和方法。继承形成了类与类之间的“是一个”关系(is-a relationship)。
12345678910111213class Animal {public: void eat() { std::cout << "Eating...\n"; }};class Dog : public Animal { // Dog 继承自 Animalpublic: void bark() { std::cout << "Barking...\n"; }};
在上述代码中,Dog 类继承自 Animal ...
相似之处间接访问对象:引用和指针都可以通过它们来间接访问和操作某个对象的值,而不是直接使用该对象的名字。
引用:通过引用可以访问和操作所引用的对象。
指针:通过指针的解引用(*)可以访问和操作指针指向的对象。
作为函数参数传递:两者都可以作为函数参数,允许函数操作调用者传递的对象,而不是对象的副本。
引用示例:123void modify(int& ref) { ref = 20; // 直接修改传入的参数}
指针示例:123void modify(int* ptr) { *ptr = 20; // 通过解引用修改传入的参数}
不同之处语法上的区别
引用:
语法上类似变量的别名,一旦定义,必须绑定到一个对象,且无法重新绑定。
使用时不需要显式解引用,访问时与直接使用变量一样。
123int x = 10;int& ref = x; // ref 是 x 的引用ref = 20; // 相当于修改 x,x 现在是 20
指针:
是一种变量,存储的是另一个对象的地址。
使用时需要通过解引用运算...
常引用(const reference)是C++中的一种引用类型,它允许你通过引用访问某个变量,但不允许通过该引用修改变量的值。常引用的主要用途是确保数据的只读性、提高性能以及避免不必要的拷贝。下面是对常引用的详细讲解:
基本语法常引用的语法是在引用类型前加上const关键字:
1const int& ref = someInt;
这个声明表示ref是someInt的一个常引用。通过ref可以读取someInt的值,但无法修改它。
常引用的主要特性
不可修改性:常引用指向的数据无法通过该引用修改。例如:
123int x = 10;const int& ref = x;ref = 20; // 错误!不能通过常引用修改 x 的值
这样确保了代码的安全性,防止意外修改。
延长临时对象的生命周期:常引用的一个重要特性是它可以绑定到临时对象(右值),并延长该临时对象的生命周期。例如:
1const int& ref = 10;
在这段代码中,10是一个右值(临时对象),如果没有常引用,临时对象会在语句结束后销毁。但使用常引用后,该临时对象会在ref的生命周...